液晶表示器で文字表示してみよう!−−その2
(4ビットインターフェースデータ長の場合)
今度は液晶表示器を、4ビットインターフェースデータ長で動作させてみましょう。8ビットモードと比較して文字コードデータを上位下位4ビットに分けて制御させます。なお、PICとの接続ですが、8ビットと比べて配線数が少ない利点を生かして、単一ポートで制御させてみましょう。「PIC活用ハンドブック」のP.336に掲載されている内容では、PORTAとPORTBを使用していますが、ここではPORTBのみで動作させることにしましょう。
ハード側の接続
図1に液晶表示器とPIC間の接続回路例を示します。図1(a)はSC1602BSLB(16文字×2行)、(b)はSC2004C(20文字×4行)のSUNLIKE社製の液晶表示器を使いました。液晶表示器のコネクタ・ピン配置の項目を参照して確実に接続してください。
詳細はこちら→コネクタ・ピン配置について
特に電源端子ですが、同じSUNLIKE社製でありながら、VDDとVSSだけが逆になっています。もしも間違えると壊れる可能性大です。差し替えの際には十分注意してください。また、コントラスト調整電源端子(Vo)ですが、10kΩの可変抵抗器で0〜5Vの電圧を供給しています。Vo=0V(VSS)で最も濃くなります。可変抵抗器がなければ、とりあえずVo端子はVSSに接続しておいてください。
なお、4ビットモードでは液晶表示器のDB0〜DB3端子は未使用となっておりますが、必ずGNDに接続してください。液晶表示器の初期化の段階では8ビットモードになっており、DB0〜DB3ピンをLowレベルにしておきます。
4ビットモードでは液晶表示器のDB0〜DB3端子は必ずGNDに接続すること
(注)オープンにしていると、初期化できない場合があります。
![]() |
図1(a).液晶表示器(16文字×2行)とPIC間の接続 (4ビット・インターフェースデータ長の場合) |
![]() |
図1(b).液晶表示器(20文字×4行)とPIC間の接続 (4ビット・インターフェースデータ長の場合) |
液晶表示動作の確認プログラム(2)
(4ビット・インターフェースデータ長の場合)
図3に液晶表示動作の確認プログラムのフローチャートを示します。
プログラムの解説については、「プログラムの説明」の項をご参照ください。
![]() ![]() |
![]() ![]() |
図3−1.液晶表示動作の確認プログラム(2) フローチャート |
![]() |
![]() |
図3−2(a).LCD・コマンド出力 4ビットモード対応の サブルーチンのフローチャート |
図3−3(a).LCD・文字データ出力 4ビットモード対応の サブルーチンのフローチャート |
![]() |
![]() |
図3−2(b).LCD・コマンド出力部の サブルーチンのフローチャート |
図3−3(b).LCD・文字データ出力部の サブルーチンのフローチャート |
![]() ![]() |
![]() ![]() |
図3−4.LCD・初期化 サブルーチンのフローチャート |
図3−5.LCD・ビジーチェック サブルーチンのフローチャート |
(注)以下に示すプログラムには、ホームページ画面作成の都合上、空白として全角文字のスペースなどが挿入されています。したがって、下記プログラムリストをそのままコピーしてMPLABのソースファイルとされた場合には、エラーとなることがあります。
→ここをクリックして、下記のプログラムをダウンロードするようにしてください。
ファイル名:「lcd_2.asm」 サイズ9.01kバイト
→ここをクリックして、下記のオブジェクトファイルをダウンロードするようにしてください。
ファイル名:「lcd_2.hex」 サイズ0.97kバイト
(注)下記のプログラムリストは、8ビットインターフェース長のプログラム(1)と比べて、おもに異なるところを青字で示しています。
なお、プログラムリストのコメントの番号ですが、8ビットインターフェース長のプログラムの説明と同等な箇所に、同じ番号を使っています。また、コメントの番号の数字の大小、順序は、特に意味はありません。
;*********************************************************** ; ; 液晶表示器(LCD)テストプログラム(2) ; (4ビットインターフェースデータ長の場合) ; ; LCDの DB7〜DB4端子は、それぞれ PIC のRB4〜RB7端子に接続 ; LCDの DB3〜DB0端子は、GNDに接続 ; LCDの RS,R/W,E端子は、それぞれ PIC のRB2,RB1,RB0端子に接続 ; ; テスト表示例は、下記の文字を表示するものとする。 ; ; SPECTRUMホームへ゜ーシ゛ ; 0123456789ABCDEF ; ;*********************************************************** |
|
LIST P=PIC16F877 INCLUDE P16F877.INC |
;(1)プロセッサの種別指定 ;(2)インクルードファイルの指定 |
;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** |
|
COUNT EQU 20H COUNT1 EQU 21H COUNT2 EQU 22H COUNT3 EQU 23H COUNT4 EQU 24H DPDT EQU 25H POINT EQU 26H RS SET 2 RW SET 1 E SET 0 BUSY_F SET 7 ORG 0 |
;(3)ループカウンタ ; ループカウンタ1 ; ループカウンタ2 ; ループカウンタ3 ; ループカウンタ4 ; 一時保存データ ; テーブルポインタ ; ; LCD レジスタ選択信号のビット番号 ; LCD 読み出し/書き込み選択信号のビット番号 ; LCD 動作起動信号のビット番号 ; ; LCD ビジーフラグのビット番号 ; ;(4)プログラムの開始番地の指定 |
;*********************************************************** ; 入出力ピン初期化 ;*********************************************************** |
|
BSF STATUS,RP0 CLRF TRISB BCF STATUS,RP0 |
;(5)Bank 1 へ切替 ;(8)全PortB 出力モードに設定 ;(9)Bank 0 へ戻す |
;*********************************************************** ; メインプログラム ;*********************************************************** |
|
START CALL LCD_INI CALL LCD_BUSY_4 MOVLW B'00001110' CALL LCD_CMD_4 CALL TIME1S |
; ;(10)液晶表示器の初期化サブルーチンへ ; ;(11)BFチェック ;(12)表示ON、カーソルON ;(13)液晶表示器へコマンド出力 ;(14)WAIT(1秒) |
TEXT_OUT1 CLRF POINT ROW_1 MOVF POINT,W CALL TABLE ADDLW 0 BTFSC STATUS,Z GOTO TEXT_OUT2 CALL LCD_DATA_4 CALL TIME1S INCF POINT,F GOTO ROW_1 |
;(15)テーブルポインタのリセット ;(16)1行目のテキストデータ表示 ;(17)テーブルポインタの値をWregへロードする(OFFSET) ;(18)テキストデータの読み込みサブルーチンへ ;(19)Wregレジスタに0を加算する ; 演算結果がゼロかチェック(テキストデータは「0」?) ; テキストデータが終了のとき TEXT_OUT2へジャンプ ; テキストデータをLCD出力するためサブルーチンへ ;(20)WAIT(1秒) ;(21)テーブルポインタ +1 ;(22)ROW_1 のラベルへ戻り繰り返す |
TEXT_OUT2 INCF POINT,F MOVLW B'11000000' CALL LCD_CMD_4 CALL TIME1S |
;(23)テーブルポインタ +1 ;(24)カーソルが2行目にくるようにアドレスセット ;(25)液晶表示器へコマンド出力 ;(26)WAIT(1秒) |
ROW_2 MOVF POINT,W CALL TABLE ADDLW 0 BTFSC STATUS,Z GOTO TEXT_CLEAR CALL LCD_DATA_4 CALL TIME1S INCF POINT,F GOTO ROW_2 |
;(27)2行目のテキストデータ表示 ;(28)テーブルポインタの値をWregへロードする(OFFSET) ;(29)テキストデータの読み込みサブルーチンへ ;(30)Wregレジスタに0を加算する ; 演算結果がゼロかチェック(テキストデータは「0」?) ; テキストデータが終了のとき TEXT_CLEARへジャンプ ; テキストデータをLCD出力するためサブルーチンへ ;(31)WAIT(1秒) ;(32)テーブルポインタ +1 ;(33)ROW_2 のラベルへ戻り繰り返す |
TEXT_CLEAR MOVLW B'00000001' CALL LCD_CMD_4 CALL TIME1S ; GOTO TEXT_OUT1 |
;(34)表示クリア ;(35)液晶表示器へコマンド出力 ;(36)WAIT(1秒) ;(37)テキスト文字を繰り返し表示する |
TABLE ADDWF PCL,F DT "SPECTRUMホームページ",0 DT "0123456789ABCDEF",0 |
; ;(38)PC+OFFSET ; ; TABLEの定義(PC+OFFSET相当のデータを持って戻る) |
;*********************************************************** ; 液晶表示器の初期化サブルーチン (39) ;*********************************************************** |
|
LCD_INI CALL TIME10M CALL TIME10M MOVLW B'00110000' CALL LCD_CMD CALL TIME10M MOVLW B'00110000' CALL LCD_CMD CALL TIME100 MOVLW B'00110000' CALL LCD_CMD CALL TIME100 MOVLW B'00100000' CALL LCD_CMD CALL LCD_BUSY_4 MOVLW B'00101000' CALL LCD_CMD_4 CALL LCD_BUSY_4 MOVLW B'00001000' CALL LCD_CMD_4 CALL LCD_BUSY_4 MOVLW B'00000001' CALL LCD_CMD_4 CALL LCD_BUSY_4 MOVLW B'00000110' CALL LCD_CMD_4 RETURN |
;(40)WAIT(10ms) ; WAIT(10ms) 10ms×2=20msを確保(15ms以上) ;(41)ファンクションセット(8bitモードに設定) ;(42)液晶表示器へコマンド出力 ;(43)WAIT(10ms)を確保(4.1ms以上) ;(44)ファンクションセット(8bitモードに設定) ;(45)液晶表示器へコマンド出力 ;(46)WAIT(100μs) ;(47)ファンクションセット(8bitモードに設定) ;(48)液晶表示器へコマンド出力 ;(46')WAIT(100μs) ;(47')ファンクションセット(4bitモード) ;(48')液晶表示器へコマンド出力 ;(49)ここからBFチェックができます ;(50)ファンクションセット(4bitモード,1/16デューティ,5×7ドット) ;(51)液晶表示器へコマンド出力 ;(52)BFチェック ;(53)表示オフ ;(54)液晶表示器へコマンド出力 ;(55)BFチェック ;(56)表示クリア ;(57)液晶表示器へコマンド出力 ;(58)BFチェック ;(59)エントリーモードセット ; (アドレスを+1し、カーソルは右移動,表示シフトはしない) ;(60)液晶表示器へコマンド出力 |
;*********************************************************** ; 液晶表示器へコマンドを出力するサブルーチン ;*********************************************************** |
|
LCD_CMD_4 MOVWF DPDT ANDLW 0F0H CALL LCD_CMD SWAPF DPDT,W ANDLW 0F0H CALL LCD_CMD RETURN LCD_CMD MOVWF PORTB BCF PORTB,RW BCF PORTB,RS BSF PORTB,E NOP BCF PORTB,E RETURN |
;(101)4ビットモード ;(102)データを一時保存 ;(103)下位4ビットをマスクする ;(104)データ出力(コマンドコードの上位4ビット相当) ;(105)一時保存データの上位下位入れ替え ;(106)下位4ビットをマスクする ;(107)データ出力(コマンドコードの下位4ビット相当) ;(61)液晶表示器へコマンドを出力するサブルーチン ;(62)DB4〜DB7(データバスの設定) ;(63)R/W = 0 (書き込みモードに設定) ;(64)RS = 0 (コマンドモードに設定) ;(65)E = 1 (動作起動信号の設定:Hでストローブ) ;(66)Eのパルス幅を220ns以上確保するためのダミー命令 ;(67)E = 0 (動作起動信号の設定:Lに戻す) |
;*********************************************************** ; 液晶表示器へデータを出力するサブルーチン ;*********************************************************** |
|
LCD_DATA_4 MOVWF DPDT ANDLW 0F0H CALL LCD_DATA SWAPF DPDT,W ANDLW 0F0H CALL LCD_DATA RETURN LCD_DATA MOVWF PORTB BCF PORTB,RW BSF PORTB,RS BSF PORTB,E NOP BCF PORTB,E RETURN |
;(111)4ビットモード ;(112)データを一時保存 ;(113)下位4ビットをマスクする ;(114)データ出力(文字コードの上位4ビット相当) ;(115)一時保存データの上位下位入れ替え ;(116)下位4ビットをマスクする ;(117)データ出力(文字コードの下位4ビット相当) ;(68)液晶表示器へデータを出力するサブルーチン ;(69)DB4〜DB7(データバスの設定) ;(70)R/W = 0 (書き込みモードに設定) ;(71)RS = 1 (データモードに設定) ;(72)E = 1 (動作起動信号の設定:Hでストローブ) ;(73)Eのパルス幅を220ns以上確保するためのダミー命令 ;(74)E = 0 (動作起動信号の設定:Lに戻す) ; |
;*********************************************************** ; ビジーチェック(BF)を行うサブルーチン ;*********************************************************** |
|
LCD_BUSY_4 BSF STATUS,RP0 MOVLW 0F0H MOVWF TRISB BCF STATUS,RP0 BCF PORTB,RS BSF PORTB,RW BSF PORTB,E MOVF PORTB,W BCF PORTB,E MOVWF DPDT BSF PORTB,E MOVF PORTB,W BCF PORTB,E BTFSC DPDT,BUSY_F GOTO LCD_BUSY_4 BCF PORTB,RW BSF STATUS,RP0 MOVLW 0H MOVWF TRISB BCF STATUS,RP0 RETURN |
;(75)ビジーチェック(BF)を行うサブルーチン ;(76)Bank 1 へ切替 ;(77)上位4ビットを入力モードに ; PortB を設定 ;(78)Bank 0 へ戻す ;(79)RS = 0 (コマンドモードに設定) ;(80)R/W = 1 (読み込みモードに設定) ;(81)E = 1 (動作起動信号の設定:Hでストローブ) ;(82)DDRAMからのデータ(上位4ビット相当)の読み出し ;(83)E = 0 (動作起動信号の設定:Lに戻す) ;(84)読み込みデータをレジスタファイルに一時保存 ;(81')E = 1 (動作起動信号の設定:Hでストローブ) ;(82')DDRAMからのデータ(下位4ビット相当)の読み出し ;(83')E = 0 (動作起動信号の設定:Lに戻す) ;(85)ビジーフラグのチェック(読み込みデータの7ビット目) ; BUSY_F=1のとき LCD_BUSY_4 間をループする ; BUSY_F=0のときループを抜ける ;(86)R/W = 0 (書き込みモードに設定) ;(87)Bank 1 へ切替 ;(88)出力モードに ; PortB を設定 ;(89)Bank 0 へ戻す ; |
;*********************************************************** ;遅延サブルーチン ;*********************************************************** ;100μs遅延サブルーチン(20MHzクロック時) ;・・・・・ 別記プログラムリスト参照・・・・・ ; ;10ms遅延サブルーチン(20MHzクロック時) ;・・・・・ 別記プログラムリスト参照・・・・・ ; ;1s遅延サブルーチン(20MHzクロック時) ;・・・・・ 別記プログラムリスト参照・・・・・ |
|
END |
【プログラムの説明】
このプログラムについて、順を追って解説を加えておきましょう。
(1)プロセッサの種別指定
定義の仕方は「PROCESSOR」か「LIST」命令を使って設定します。ここで指定するプロセッサ名称は、パッケージの種類を示すサフィックス(最後の英記号の部分)は不要です。
PROCESSOR PIC16F877
または
LIST P=PIC16F877
(2)標準ヘッダーファイルのインクルード
標準ヘッダーファイルとは、各プロセッサが持っているSFR(Special Function Register)をラベル(記号)で使える
ため、ラベルとハードウェアの場所とを定義しているファイルです。標準ヘッダーファイルは 「プロセッサ名.INC」というファイル名で統一されて、MPLABのディレクトリに格納されています。従って、これのインクルード方法は下記のようにして行います。
一度、参考までに標準ヘッダーファイルの内容をエディタ等で見ておくことをお勧めします。
INCLUDE P16F877.INC
または
#INCLUDE P16F877.INC
(3)変数定義とレジスタ割付
レジスタファイルアドレスを指定するときに、アドレス数値を直接指定することもできますが、数値だけでは間違いも多く、プログラム自身も分かりにくくなってしまいます。そこで、EQU命令などを使ってラベルを設定し変数を定義します。レジスタファイルアドレスは、7ビットあるので、00〜7Fまで最大128個のレジスタが指定できますが、実際に物理的に実装されて汎用的に使用できるレジスタ数はデバイスによって異なっていますので注意が必要です。
PIC16F877の汎用レジスタのアドレスは、20H〜7FH
となっていますので、20H以降のアドレスに割り付けます。
(4)プログラムの開始番地の指定
「ORG」はプログラムの開始番地を指定する擬似命令で、ORG以下の実際のプログラム命令が格納されるプログラムメモリ内の位置(アドレス)を指定します。
ORG 0 ;0番地から格納することを示します。
コンピュータは一般に電源投入時やリセットをすると必ず0番地からスタートするようになっているので、0番地には必ず命令があることが必要です。
(5)Bank 1 へ切替
PICには各種の動作モードを設定するための Special
Register と呼ばれるものが用意されています。PICを動作させるためには、まずこのSpecial
Registerの設定から始めます。そしてそれらは全て、Register
File と呼ぶメモリとして用意されています。その
Register Fileは Bank0, Bank1, Bank2, Bank3
とよばれるアドレス空間をもっているため、多少アクセスの仕方が面倒です。つまりRESET後の通常はBank0となっているので、Bank1側のレジスタにアクセスするときはBankの切替えをしてからとなります。またBank0とBank1に同じ物があるときにはどちらでも同じ様に使えます。
Bank1へ切り替える方法ですが、「STATUS」レジスタにある2ビットのRP0、RP1を変えてBankを指定します。デフォルトは、Bank0です。表1にBankとRP1,RP0ビットとの関係を示します。Bank1へ切り替えるためには、RP0ビットを「1」にします。(RP1はデフォルトで「0」なので変える必要はない。)
BSF STATUS,RP0
「STATUS」レジスタのRP0ビットを「1」にする。
Bank | RP1 | RP0 |
0 | 0 | 0 |
1 | 0 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
(6)〜(7)PORTAは使用しないため、省略可
(8)PORTB 全ポートを出力に設定
TRISBレジスタを、CLRF(fレジスタをゼロクリアする命令)で出力設定とします。
CLRF TRISB
「TRISBレジスタをゼロクリアする。すなわち、PORTB全ポートを出力に設定する」
(9)Bank 0 へ戻す
Bank1での設定が終了した後は、Bank0に戻しておきます。Bank1へ切り替えるためには、RP0ビットを「0」にします。(RP1はデフォルトで「0」なので変える必要はない。)
BCF STATUS,RP0
「STATUS」レジスタのRP0ビットを「0」にする。すなわち、Bank0に戻す。」
(10)液晶表示器の初期化サブルーチンへ
液晶表示器を使用する前に、初期化しておきます。ここでは、LCD_INIというラベルの付いたサブルーチンへジャンプします。
(11)BFチェック
液晶表示器の初期化が完了したかどうか確認のため、
Busy Flagのチェックをします。LCD_BUSY_4 というラベルの付いたサブルーチンへジャンプします。
(12)表示ON、カーソルON
液晶表示器の初期化後は、表示がOFFとなっているため、表示やカーソルの有無指定をします。
このインストラクションの詳細については、表示オン/オフコントロールを参照
(13)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(14)WAIT(1秒)
液晶表示器の画面の変化が、人間の目で分かるように1秒間のウエイトを入れました。TIME1Sというラベルの付いたサブルーチンへジャンプします。
(15)テーブルポインタのリセット
POINTという変数を使い、表示させる文字列テーブルの文字位置を指し示すようにしました。最初の文字から表示させるため、ここでPOINT変数の値をクリアしておきます。
(16)1行目のテキストデータ表示
ここのラベル「ROW_1」以降のルーチンにより、液晶表示器の1行目にテキストを表示します。
(17)テーブルポインタの値をWregへロードする
文字列テーブルのポインタ値をワーキングレジスタへロードします。
(18)テキストデータの読み込みサブルーチンへ
表示させる文字列テーブル TABLEというラベルの付いたサブルーチンへジャンプします。
(19)Wregレジスタに0を加算する
演算結果がゼロかチェック(テキストデータは「0」?)
テキストデータが終了のとき TEXT_OUT2へジャンプ
テキストデータがあればLCD出力するためのサブルーチンへ
テキストデータの読み込みサブルーチンから戻ってきたときに、ワーキングレジスタに文字コードを入れて戻ってきます。ただし、文字列の終了を判断するのに、”0”を使っています。ここでワーキングレジスタの内容が”0”であれば、演算結果が”0”になるのでゼロフラグが立ちます。一方、ワーキングレジスタの内容に文字コードが入っていれば、”0”を加算しても文字コードの値は変化しません。すなわち、表示する文字があればLCD_DATA_4
というサブルーチンへジャンプして表示し、終了すれば次の段階のTEXT_OUT2へジャンプする条件分岐を行っています。
(20)WAIT(1秒)
液晶表示器の画面の変化が、人間の目で分かるように1秒間のウエイトを入れました。TIME1Sというラベルの付いたサブルーチンへジャンプします。
(21)テーブルポインタ +1
次の文字表示を行うためテーブルポインタの値を+1します。テーブルポインタの値は、プログラムカウンタにテーブルポインタの値(OFFSET分)を足し合わせることで、表示文字が記載されたテーブルの位置関係を指し示すようになっています。
(22)ROW_1 のラベルへ戻り繰り返す
次の文字表示を行うため、ROW_1 のラベルへ戻り繰り返します。
(23)テーブルポインタ +1
2行目からの文字表示を行うためテーブルポインタの値を+1します。
(24)カーソルが2行目にくるようにアドレスセット
カーソルを2行目の先頭に来るように液晶表示器のアドレスをセットします。
アドレスの値は、40になります。詳細は液晶表示器の内部アドレスを参照してください。またアドレスセットのインストラクションについては、DDRAMアドレスセットを参照してください。 ここでは、B’11000000’になります。
(25)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(26)WAIT(1秒)
液晶表示器の画面の変化が、人間の目で分かるように1秒間のウエイトを入れました。TIME1Sというラベルの付いたサブルーチンへジャンプします。
(27)2行目のテキストデータ表示
ここのラベル「ROW_2」以降のルーチンにより、液晶表示器の2行目にテキストを表示します。
(28)テーブルポインタの値をWregへロードする
文字列テーブルのポインタ値をワーキングレジスタへロードします。
(29)テキストデータの読み込みサブルーチンへ
表示させる文字列テーブル TABLEというラベルの付いたサブルーチンへジャンプします。
(30)Wregレジスタに0を加算する
演算結果がゼロかチェック(テキストデータは「0」?)
テキストデータが終了のとき TEXT_CLEARへジャンプ
テキストデータがあればLCD出力するためのサブルーチンへ
テキストデータの読み込みサブルーチンから戻ってきたときに、ワーキングレジスタに文字コードを入れて戻ってきます。ただし、文字列の終了を判断するのに、”0”を使っています。ここでワーキングレジスタの内容が”0”であれば、演算結果が”0”になるのでゼロフラグが立ちます。一方、ワーキングレジスタの内容に文字コードが入っていれば、”0”を加算しても文字コードの値は変化しません。すなわち、表示する文字があればLCD_DATA_4
というサブルーチンへジャンプして表示し、終了すれば次の段階のTEXT_CLEARへジャンプする条件分岐を行っています。
(31)WAIT(1秒)
液晶表示器の画面の変化が、人間の目で分かるように1秒間のウエイトを入れました。TIME1Sというラベルの付いたサブルーチンへジャンプします。
(32)テーブルポインタ +1
次の文字表示を行うためテーブルポインタの値を+1します。テーブルポインタの値は、プログラムカウンタにテーブルポインタの値(OFFSET分)を足し合わせることで、表示文字が記載されたテーブルの位置関係を指し示すようになっています。
(33)ROW_2 のラベルへ戻り繰り返す
次の文字表示を行うため、ROW_2 のラベルへ戻り繰り返します。
(34)表示クリア
液晶表示器の2行目まで文字表示の終了後、1行目に戻って繰り返し表示を行うため、表示をクリアします。
このインストラクションの詳細については、表示クリアを参照
(35)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(36)WAIT(1秒)
液晶表示器の画面の変化が、人間の目で分かるように1秒間のウエイトを入れました。TIME1Sというラベルの付いたサブルーチンへジャンプします。
(37)テキスト文字を繰り返し表示する
最初から文字表示を行うため、TEXT_OUT1のラベルへ戻り繰り返します。
(38)TABLEの定義(PC+OFFSET相当のデータを持って戻る)
PC+OFFSET
データテーブルのサブルーチンに来ると、プログラムカウンタに、Wregの値(オフセット)が加算されます。その加算結果をプログラムカウンタとしますので、そのテーブルポインタ(アドレス)で指定されたデータを示すようになります。
ADDWF PCL,F ;プログラムカウンタに、Wregの値(オフセット)を加算し、
その加算結果をプログラムカウンタする。
(39)液晶表示器の初期化サブルーチン
詳細はインストラクションによる初期設定をご覧ください。
(40)WAIT(10ms)
WAIT(10ms) 10ms×2=20msを確保(15ms以上)
液晶表示器の電源が4.5V以上に達してから、15ms以上のウエイトを入れます。ここでは10msのサブルーチンへ2回ジャンプすることで、20msを確保しています。
(41)ファンクションセット(8bitモードに設定)
このインストラクションの詳細については、ファンクションセットを参照
(42)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMDというラベルの付いたサブルーチンへジャンプします。
(43)WAIT(10ms)を確保(4.1ms以上)
上記のインストラクションの実行後、4.1ms以上のウエイトを入れます。ここでは10msのサブルーチンへジャンプすることで、10msを確保しています。
(44)ファンクションセット(8bitモードに設定)
このインストラクションの詳細については、ファンクションセットを参照
(45)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMDというラベルの付いたサブルーチンへジャンプします。
(46)WAIT(100μs)
上記のインストラクションの実行後、100μs以上のウエイトを入れます。ここでは100μsのサブルーチンへジャンプすることで、100μsを確保しています。
(47)ファンクションセット(8bitモードに設定)
このインストラクションの詳細については、ファンクションセットを参照
(48)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMDというラベルの付いたサブルーチンへジャンプします。
(46’)WAIT(100μs)
上記のインストラクションの実行後、100μs以上のウエイトを入れます。ここでは100μsのサブルーチンへジャンプすることで、100μsを確保しています。
(47’)ファンクションセット(4bitモードに設定)
このインストラクションの詳細については、ファンクションセットを参照
(48’)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMDというラベルの付いたサブルーチンへジャンプします。
(49)ここからBFチェックができます
上記のインストラクションが完了したかどうか確認のため、
Busy Flagのチェックをします。LCD_BUSY_4 というラベルの付いたサブルーチンへジャンプします。
(50)ファンクションセット(4bitモード,1/16デューティ,5×7ドット)
このインストラクションの詳細については、ファンクションセットを参照
(51)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(52)BFチェック
上記のインストラクションが完了したかどうか確認のため、
Busy Flagのチェックをします。LCD_BUSY_4 というラベルの付いたサブルーチンへジャンプします。
(53)表示オフ
液晶表示器の初期化として表示をオフします。 このインストラクションの詳細については、表示オン/オフコントロールを参照
(54)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(55)BFチェック
上記のインストラクションが完了したかどうか確認のため、
Busy Flagのチェックをします。LCD_BUSY_4 というラベルの付いたサブルーチンへジャンプします。
(56)表示クリア
液晶表示器の初期化として表示をクリアします。 このインストラクションの詳細については、表示クリアを参照
(57)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(58)BFチェック
上記のインストラクションが完了したかどうか確認のため、
Busy Flagのチェックをします。LCD_BUSY_4 というラベルの付いたサブルーチンへジャンプします。
(59)エントリーモードセット
アドレスを+1し、カーソルは右移動,表示シフトはしない)
液晶表示器の初期化としてエントリーモードをセットします。 このインストラクションの詳細については、エントリーモードセットを参照
(60)液晶表示器へコマンド出力
上記のインストラクションを実行させるため、液晶表示器へコマンドを出力します。LCD_CMD_4
というラベルの付いたサブルーチンへジャンプします。
(101)液晶表示器へコマンドコードを出力するサブルーチン(4ビットモード)
4ビットモードでインストラクションを実行させるためのサブルーチンです。
(102)データを一時保存
DPDT変数にコマンドデータを格納しておきます。
(103)下位4ビットをマスクする
4ビットモードでインストラクションを実行させるため、下位4ビットをマスク(無効)にします。
(104)データ出力(コマンドコードの上位4ビット相当)
コマンドコードのデータを出力するサブルーチンへ
(105)一時保存データの上位下位入れ替え
DPDT変数に格納しておいたコマンドデータの上位下位を入れ替え、ワーキングレジスタに格納します。
(106)下位4ビットをマスクする
4ビットモードでインストラクションを実行させるため、下位4ビットをマスク(無効)にします。
(107)データ出力(コマンドコードの下位4ビット相当)
コマンドコードのデータを出力するサブルーチンへ
(61)液晶表示器へコマンドを出力するサブルーチン
インストラクションを実行させるためのサブルーチンです。各信号の制御関係については、制御信号のタイムチャートを参照してください。
(62)DB4〜DB7(データバスの設定)
インストラクションの設定データをRBポートに出力します。
(63)R/W = 0 (書き込みモードに設定)
リード/ライト選択信号(H=読み込み,L=書き込み)を書き込みモードに設定します。
(64)RS = 0 (コマンドモードに設定)
レジスタ選択信号、すなわちコマンド/データ選択(H=データ,L=コマンド)をコマンドモードに設定します。
(65)E = 1 (動作起動信号の設定:Hでストローブ)
動作起動信号をHレベルにして、各データをストローブします。
(66)Eのパルス幅を220ns以上確保するためのダミー命令
動作起動信号のパルス幅を220ns以上に確保するためにNOP命令を入れておきます。連続してON,OFFした場合、PIC命令の1サイクルの実行時間は、1サイクル実行時間=4/クロック周波数となっていますので、クロック周波数が20MHz(50ns)の場合は、4/20MHz=4*50ns=200nsとなります。1命令文で連続してON,OFFした場合、20MHzのクロック周波数では、十分なパルス幅を確保できません。したがって、間にNOP命令などを挿入して十分なパルス幅をとる必要があります。
(67)E = 0 (動作起動信号の設定:Lに戻す)
動作起動信号をLレベルにして、設定が完了します。
(111)液晶表示器へ文字コードを出力するサブルーチン(4ビットモード)
4ビットモードによる文字コード設定のためのサブルーチンです。
(112)データを一時保存
DPDT変数にコマンドデータを格納しておきます。
(113)下位4ビットをマスクする
4ビットモードによる文字コード設定のため、下位4ビットをマスク(無効)にします。
(114)データ出力(文字コードの上位4ビット相当)
文字コードのデータを出力するサブルーチンへ
(115)一時保存データの上位下位入れ替え
DPDT変数に格納しておいた文字コードデータの上位下位を入れ替え、ワーキングレジスタに格納します。
(116)下位4ビットをマスクする
4ビットモードによる文字コード設定のため、下位4ビットをマスク(無効)にします。
(117)データ出力(文字コードの下位4ビット相当)
文字コードのデータを出力するサブルーチンへ
(68)液晶表示器へデータを出力するサブルーチン
インストラクションを実行させるためのサブルーチンです。各信号の制御関係については、制御信号のタイムチャートを参照してください。
(69)DB4〜DB7(データバスの設定)
インストラクションの設定データをRBポートに出力します。
(70)R/W = 0 (書き込みモードに設定)
リード/ライト選択信号(H=読み込み,L=書き込み)を書き込みモードに設定します。
(71)RS = 1 (データモードに設定)
レジスタ選択信号、すなわちコマンド/データ選択(H=データ,L=コマンド)をデータモードに設定します。
(72)E = 1 (動作起動信号の設定:Hでストローブ)
動作起動信号をHレベルにして、各データをストローブします。
(73)Eのパルス幅を220ns以上確保するためのダミー命令
動作起動信号のパルス幅を220ns以上に確保するためにNOP命令を入れておきます。
(74)E = 0 (動作起動信号の設定:Lに戻す)
動作起動信号をLレベルにして、設定が完了します。
(75)ビジーチェック(BF)を行うサブルーチン
以前に受けたインストラクションによって、モジュールが内部動作中である間はループを繰り返し、インストラクションが完了するとメインルーチンへ戻るサブルーチンです。なお、制御信号の関係については、制御信号のタイムチャート(読み込み時)を参照してください。
(76)Bank 1 へ切替
RBポートを入力モードに設定するために、Bank1へ切り替えます。
(77)上位4ビットを入力モードに
液晶表示器のデータバスに接続されている端子(RB4〜RB7のポート)を入力モードに設定します。
TRISBレジスタの上位4ビットを”1”にすることで入力モードになります。下位3ビットは”0”で出力モード(RS,R/W,E)です。なお、RB3は未接続のため、入出力関係はどちらでもよいです。
(78)Bank 0 へ戻す
Bank1での設定が終了した後は、Bank0に戻しておきます。
(79)RS = 0 (コマンドモードに設定)
レジスタ選択信号、すなわちコマンド/データ選択(H=データ,L=コマンド)をコマンドモードに設定します。
(80)R/W = 1 (読み込みモードに設定)
リード/ライト選択信号(H=読み込み,L=書き込み)を読み込みモードに設定します。
(81)E = 1 (動作起動信号の設定:Hでストローブ)
動作起動信号をHレベルにして、各データをストローブします。
(82)DDRAMからのデータ(上位4ビット相当)の読み出し
RBポートからDDRAMの上位4ビット相当のデータを読み出します。
(83)E = 0 (動作起動信号の設定:Lに戻す)
動作起動信号をLレベルにして、設定が完了します。
(84)読み込みデータをレジスタファイルに一時保存
DPDT変数にデータを格納しておきます。
(81’)E = 1 (動作起動信号の設定:Hでストローブ)
動作起動信号をHレベルにして、各データをストローブします。
(82’)DDRAMからのデータ(下位4ビット相当)の読み出し
RBポートからDDRAMの下位4ビット相当のデータを読み出します。(注)ここでは読み出すという一連の動作が必要であって、読み出された下位4ビット相当のデータには、特に意味はありません。(ダミーデータの読み出し動作)
(83’)E = 0 (動作起動信号の設定:Lに戻す)
動作起動信号をLレベルにして、設定が完了します。
(85)ビジーフラグのチェック(読み込みデータの7ビット目)
BUSY_F=1のときLCD_BUSY_4 間をループする
BUSY_F=0のときループを抜ける
DPDT変数に格納されているデータの7ビット目がビジーフラグ(BF)です。このインストラクションの詳細については、ビジーフラグ/アドレス読み出しを参照してください。条件分岐は、BF=1のときループし、0のときループから抜け出るようになっています。
(86)R/W = 0 (書き込みモードに設定)
(80)でリード/ライト選択信号(H=読み込み,L=書き込み)を書き込みにモードに戻しておきます。
(87)Bank 1 へ切替
RBポートを出力モードに戻しておくために、Bank1へ切り替えます。
(88)出力モードにPortB を設定
TRISBレジスタの全ビットを”0”にすることで出力モードに設定します。
(89)Bank 0 へ戻す
Bank1での設定が終了した後は、Bank0に戻しておきます。
ポートの誤動作防止について
BSF,BCFなどのビット操作命令で、同じポートに出力する場合には、間にダミーとしてNOP命令などを入れる
ここは、(63)〜(65)の各コマンド間、及び(70)〜(72)の各コマンド間、及び(79)〜(82)の各コマンド間のように、BSF,BCFなどのビット操作命令により同一ポートを続けて設定していると、ポートが誤動作をすることがあります。BSF,BCFなどのビット操作命令は、一度ポートレジスタのすべてのビットの状態を読み込み、指定ビットのみを変更して再度ポートレジスタに上書きするという操作がされます。すなわち、最初の命令 たとえば(63)の出力がなされ、次の命令(64)が出力される前に、一度入力動作があるのです。最初の命令の出力と次の命令の入力動作の間は、1クロック分しかなく、20MHzクロックの場合にはわずかに50nsecです。出力ピンの負荷に何らかの容量成分があると、信号の立ち上がりや立ち下がりが遅れるため、最初の命令の出力が完全に落ち着く前に次の命令で読み込みを実行してしまうため誤動作が発生しやすくなります。この対策としては、ビット操作命令で連続して同じポートに出力する場合には、間にNOP命令など他の命令を最低1個挿入するようにします。
(81)と(82)間についてもNOPを挿入しました。(2001.6.11 高山さんのメッセージを参照)
;*********************************************************** ; 液晶表示器へコマンドを出力するサブルーチン ;*********************************************************** ・・・・・ 中略 ・・・・・ |
|
LCD_CMD MOVWF PORTB BCF PORTB,RW NOP BCF PORTB,RS NOP BSF PORTB,E NOP BCF PORTB,E RETURN |
;(61)液晶表示器へコマンドを出力するサブルーチン ;(62)DB4〜DB7(データバスの設定) ;(63)R/W = 0 (書き込みモードに設定) ; 誤動作防止のダミー命令 ;(64)RS = 0 (コマンドモードに設定) ; 誤動作防止のダミー命令 ;(65)E = 1 (動作起動信号の設定:Hでストローブ) ;(66)Eのパルス幅を220ns以上確保するためのダミー命令 ;(67)E = 0 (動作起動信号の設定:Lに戻す) |
;*********************************************************** ; 液晶表示器へデータを出力するサブルーチン ;*********************************************************** ・・・・・ 中略 ・・・・・ |
|
LCD_DATA MOVWF PORTB BCF PORTB,RW NOP BSF PORTB,RS NOP BSF PORTB,E NOP BCF PORTB,E RETURN |
;(68)液晶表示器へデータを出力するサブルーチン ;(69)DB4〜DB7(データバスの設定) ;(70)R/W = 0 (書き込みモードに設定) ; 誤動作防止のダミー命令 ;(71)RS = 1 (データモードに設定) ; 誤動作防止のダミー命令 ;(72)E = 1 (動作起動信号の設定:Hでストローブ) ;(73)Eのパルス幅を220ns以上確保するためのダミー命令 ;(74)E = 0 (動作起動信号の設定:Lに戻す) ; |
;*********************************************************** ; ビジーチェック(BF)を行うサブルーチン ;*********************************************************** |
|
LCD_BUSY_4 BSF STATUS,RP0 MOVLW 0F0H MOVWF TRISB BCF STATUS,RP0 BCF PORTB,RS NOP BSF PORTB,RW NOP BSF PORTB,E NOP MOVF PORTB,W BCF PORTB,E MOVWF DPDT BSF PORTB,E MOVF PORTB,W BCF PORTB,E BTFSC DPDT,BUSY_F GOTO LCD_BUSY_4 BCF PORTB,RW BSF STATUS,RP0 MOVLW 0H MOVWF TRISB BCF STATUS,RP0 RETURN |
;(75)ビジーチェック(BF)を行うサブルーチン ;(76)Bank 1 へ切替 ;(77)上位4ビットを入力モードに ; PortB を設定 ;(78)Bank 0 へ戻す ;(79)RS = 0 (コマンドモードに設定) ; 誤動作防止のダミー命令 ;(80)R/W = 1 (読み込みモードに設定) ; 誤動作防止のダミー命令 ;(81)E = 1 (動作起動信号の設定:Hでストローブ) ; 誤動作防止のダミー命令 ;(82)DDRAMからのデータ(上位4ビット相当)の読み出し ;(83)E = 0 (動作起動信号の設定:Lに戻す) ;(84)読み込みデータをレジスタファイルに一時保存 ;(81')E = 1 (動作起動信号の設定:Hでストローブ) ;(82')DDRAMからのデータ(下位4ビット相当)の読み出し ;(83')E = 0 (動作起動信号の設定:Lに戻す) ;(85)ビジーフラグのチェック(読み込みデータの7ビット目) ; BUSY_F=1のとき LCD_BUSY_4 間をループする ; BUSY_F=0のときループを抜ける ;(86)R/W = 0 (書き込みモードに設定) ;(87)Bank 1 へ切替 ;(88)出力モードに ; PortB を設定 ;(89)Bank 0 へ戻す ; |
液晶表示の動作確認
図4に(a)16文字×2行の液晶表示器での表示例、(b)20文字×4行の液晶表示器での表示例を示します。表示動作は、左上から「SPECTRUMホームヘ゜ーシ゛」と1秒おきに順に表示し、次に2行目に移って「0123456789ABCDEF」と順に表示していきます。表示が終わるとクリアされて最初からまた表示を繰り返します。
(注)図4の表示例は、2行目の「C」が表示された段階で撮影されたものです。制御はPORTBだけのため、8ビットモード時と比べて配線がスッキリしています。
![]() |
![]() |
図4(a).16文字×2行の 液晶表示器の例 |
図4(b).20文字×4行の 液晶表示器の例 |
![]() |
|
![]() |